package com.sz.jinzheng.filter;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sz.jinzheng.model.Role;
import com.sz.jinzheng.until.JwtUntil;
import io.jsonwebtoken.Claims;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @Description: MyFilter
 * @author: Sheep
 * @date: 2021年07月07日 14:34
 */
@Slf4j
@Component
public class MyFilter extends ZuulFilter {
    /**
     * 引入redis模板 为了拿到redis中的token
     */
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 注入jwt工具类
     */
    @Autowired
    private JwtUntil jwtUntil;

    /**
     * filterType：返回一个字符串代表过滤器的类型，在zuul中定义了四种不同生命周期的过滤器类型，具体如下：
     * pre：路由之前
     * routing：路由之时
     * post： 路由之后
     * error：发送错误调用
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * filterOrder：过滤的顺序 int order的数值越小 则优先级越高
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 返回一个 boolean 类型来判断该过滤器是否要执行，所以通过此函数可实现过滤器 的开关
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        log.info("拦截住了");
        //获取上下文
        RequestContext context = RequestContext.getCurrentContext();
        //获得本次请求域
        HttpServletRequest request = context.getRequest();
        String url = request.getRequestURL().toString();


        //放开对应连接的访问权限
        if (url.contains("/login") || url.contains("/register") || url.contains("logout")||url.contains("message")) {
            return null;
        }
        //获得前端传来的token
        String token = request.getHeader("auth");
        log.info(token);
        String redisToken = "";
        Claims claims = null;
        if (StringUtils.isNotEmpty(token)) {
            try {
                //token不为空
                claims = jwtUntil.parseToken(token);
                //解析出token中的手机号码(手机号唯一这手机号就是把toke存入redis的key)
                String phone = claims.getSubject();
                //获得redis中的token
                redisToken = redisTemplate.opsForValue().get(phone);
            } catch (Exception e) {
                context.setSendZuulResponse(false);
                context.setResponseStatusCode(403);
                context.setResponseBody("请登录后再进行访问");
                context.getResponse().setContentType("text/html;charset=UTF-8");
                return null;
            }
            if (redisToken.equals(token)) {
                //获得token中放的json数据(用户角色变成json放入token)
                List<Role> roles = JSON.parseArray((String) claims.get("roles"), Role.class);
                log.info(roles.toString());
                //循环遍历对应用户角色,指定角色访问指定连接才可放行
                for (Role r : roles) {
                    if ("admin".equals(r.getRname()) && url.contains("/admin")) {
                        return null;
                    }
                    if ("user".equals(r.getRname()) && url.contains("/user")) {
                        return null;
                    }
                    if ("manager".equals(r.getRname()) && url.contains("/manager")) {
                        return null;
                    }
                    if ("inspector".equals(r.getRname()) && url.contains("/inspector")) {
                        return null;
                    }
                    if ("distribution".equals(r.getRname()) && url.contains("/distribution")) {
                        return null;
                    }
                }
            } else {
                //token不同则不进行转发
                context.setSendZuulResponse(false);
                context.setResponseStatusCode(403);
                context.setResponseBody("请登录后再进行访问");
                context.getResponse().setContentType("text/html;charset=UTF-8");
            }


        } else {
            //token不同则不进行转发
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(403);
            context.setResponseBody("请登录后再进行访问");
            context.getResponse().setContentType("text/html;charset=UTF-8");
        }
        return null;
    }
}
